home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 426-450 / disk_436 / keymacro / keymacro.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  25KB  |  1,260 lines

  1. /****************************************************************************
  2. *
  3. *    KeyMacro.c ------------    KeyMacro main process.
  4. *
  5. *    Author ----------------    Olaf Barthel, MXM
  6. *                Brabeckstrasse 35
  7. *                D-3000 Hannover 71
  8. *
  9. *    KeyMacro  ©  Copyright  1990  by  MXM;  Executable  program,
  10. *    documentation  and  source  code are shareware.  If you like
  11. *    this  program  a  small donation will entitle you to receive
  12. *    updates and new programs from MXM.
  13. *
  14. ****************************************************************************/
  15.  
  16.     /* Buffered IO include. */
  17.  
  18. #include "MRArpFile.h"
  19.  
  20.     /* Function prototypes. */
  21.  
  22. VOID            SimpleRequest(char *Args,...);
  23. VOID            EraseGadget(struct RastPort *RPort,struct Gadget *Gadget,LONG Colour);
  24. BYTE            PopRequest(struct Window *pr_ParentWindow,UBYTE *pr_TitleText,UBYTE *pr_BodyText,UBYTE *pr_PosText,UBYTE *pr_NegText,BYTE pr_Default);
  25.  
  26. UBYTE *            GetToken(UBYTE *s,LONG *start);
  27. struct MacroKey *    AddMacroKey(struct MacroKey *MacroKey);
  28. BYTE            Interprete(UBYTE *String,LONG Line);
  29. BYTE            UpdateList(char *Name);
  30. BYTE            GetDefaultKeyMap(VOID);
  31. BYTE            UStrCmp(UBYTE *a,UBYTE *b);
  32.  
  33. VOID *            SendMacroMsg(struct MacroMessage *scm_Msg,struct MsgPort *scm_Port);
  34. VOID *            AllocRem(LONG ByteSize,LONG Requirements);
  35. VOID *            FreeRem(LONG *MemoryBlock);
  36. ULONG            KeyInvert(UBYTE AnsiKey,struct InputEvent *Event,struct KeyMap *KeyMap);
  37.  
  38. VOID            main(int argc,char **argv);
  39.  
  40.     /* The Arp CLI-Interface data. */
  41.  
  42. char *CLI_Template    = "Startup,Q=Quit/s,D=Delay/k,I=Info/s";
  43. char *CLI_Help        = "\nUsage: \33[1mKeyMacro\33[0m <Startup File> [Quit] [Delay <Microseconds>] [Info]\n";
  44.  
  45. enum { ARG_STARTUP = 1, ARG_QUIT, ARG_DELAY, ARG_INFO };
  46.  
  47. extern int         Enable_Abort;
  48.  
  49.     /* Easy macro. */
  50.  
  51. #define From_CLI    (ThatsMe -> pr_CLI)
  52.  
  53.     /* Global and shared data structures. */
  54.  
  55. extern struct ExecBase        *SysBase;
  56. extern struct IntuitionBase    *IntuitionBase;
  57. extern struct GfxBase        *GfxBase;
  58. struct MSeg            *MSeg;
  59. struct MacroKey            *KeyList;
  60.  
  61.     /* We use this list to identify the non-ascii keys. */
  62.  
  63. struct KeyAlias KeyTab[22] =
  64. {
  65.     {"TAB",        0x42},
  66.     {"ESC",        0x45},
  67.     {"SPACE",    0x40},
  68.     {"RETURN",    0x44},
  69.     {"ENTER",    0x43},
  70.     {"DEL",        0x46},
  71.     {"BACKSPACE",    0x41},
  72.     {"HELP",    0x5F},
  73.     {"LEFT",    0x4F},
  74.     {"RIGHT",    0x4E},
  75.     {"UP",        0x4C},
  76.     {"DOWN",    0x4D},
  77.  
  78.     {"F1",        0x50},
  79.     {"F2",        0x51},
  80.     {"F3",        0x52},
  81.     {"F4",        0x53},
  82.     {"F5",        0x54},
  83.     {"F6",        0x55},
  84.     {"F7",        0x56},
  85.     {"F8",        0x57},
  86.     {"F9",        0x58},
  87.     {"F10",        0x59}
  88. };
  89.  
  90.     /* These are the qualifiers. */
  91.  
  92. struct KeyAlias QualifierTab[9] =
  93. {
  94.     {"NONE",    0},
  95.     {"CTRL",    IEQUALIFIER_CONTROL},
  96.     {"NUMPAD",    IEQUALIFIER_NUMERICPAD},
  97.     {"LSHIFT",    IEQUALIFIER_LSHIFT},
  98.     {"RSHIFT",    IEQUALIFIER_RSHIFT},
  99.     {"LALT",    IEQUALIFIER_LALT},
  100.     {"RALT",    IEQUALIFIER_RALT},
  101.     {"LAMIGA",    IEQUALIFIER_LCOMMAND},
  102.     {"RAMIGA",    IEQUALIFIER_RCOMMAND}
  103. };
  104.  
  105.     /* Our current version tag. */
  106.  
  107. const char *VersionTag = "\0$VER: KeyMacro 1.8 (1 Dec 1990)\n\r";
  108.  
  109. VOID
  110. SimpleRequest(char *Args,...)
  111. {
  112.     char     String[512];
  113.     va_list     VarArgs;
  114.  
  115.     va_start(VarArgs,Args);
  116.     ArpVSPrintf(String,Args,VarArgs);
  117.  
  118.     PopRequest(NULL,(UBYTE *)"KeyMacro Request",(UBYTE *)String,NULL,NULL,FALSE);
  119.  
  120.     va_end(VarArgs);
  121. }
  122.  
  123. VOID
  124. EraseGadget(struct RastPort *RPort,struct Gadget *Gadget,LONG Colour)
  125. {
  126.     BYTE FgPen = RPort -> FgPen;
  127.  
  128.     SetAPen(RPort,Colour);
  129.     RectFill(RPort,Gadget -> LeftEdge,Gadget -> TopEdge,Gadget -> LeftEdge + Gadget -> Width - 1,Gadget -> TopEdge + Gadget -> Height - 1);
  130.     SetAPen(RPort,FgPen);
  131. }
  132.  
  133. VOID
  134. CalcDimensions(UBYTE *cd_String,LONG *cd_Width,LONG *cd_Height,LONG cd_MaxWidth)
  135. {
  136.     LONG i,cd_InLine = 0,cd_NumLines = 0;
  137.  
  138.     *cd_Width = *cd_Height = 0;
  139.  
  140.     for(i = 0 ; i < strlen((char *)cd_String) ; i++)
  141.     {
  142.         if(cd_String[i] == '\n' || cd_InLine == cd_MaxWidth)
  143.         {
  144.             if(cd_InLine > *cd_Width)
  145.                 *cd_Width = cd_InLine;
  146.  
  147.             cd_NumLines++;
  148.             cd_InLine = 0;
  149.  
  150.             continue;
  151.         }
  152.  
  153.         if(cd_String[i] == '\33')
  154.         {
  155.             while(cd_String[i] != 'm' && cd_String[i] != 'w' && i < strlen((char *)cd_String))
  156.                 i++;
  157.  
  158.             if(i >= strlen((char *)cd_String))
  159.                 i = strlen((char *)cd_String) - 1;
  160.  
  161.             continue;
  162.         }
  163.  
  164.         if(cd_String[i] < ' ')
  165.             continue;
  166.  
  167.         cd_InLine++;
  168.     }
  169.  
  170.     *cd_Height = cd_NumLines;
  171.  
  172.     if(cd_InLine > *cd_Width)
  173.         *cd_Width = cd_InLine;
  174. }
  175.  
  176. BYTE
  177. WriteConsole(struct Window *wc_Window,UBYTE *wc_String)
  178. {
  179.     struct IOStdReq    *wc_ConWrite;
  180.     struct MsgPort    *wc_ConPort;
  181.  
  182.     BYTE wc_Success = FALSE;
  183.  
  184.     if(wc_ConPort = (struct MsgPort *)CreatePort(NULL,0))
  185.     {
  186.         if(wc_ConWrite = (struct IOStdReq *)CreateStdIO(wc_ConPort))
  187.         {
  188.             wc_ConWrite -> io_Data        = (APTR)wc_Window;
  189.             wc_ConWrite -> io_Length    = sizeof(struct Window);
  190.  
  191.             if(!OpenDevice("console.device",0,wc_ConWrite,0))
  192.             {
  193.                 wc_ConWrite -> io_Command    = CMD_WRITE;
  194.                 wc_ConWrite -> io_Data        = (APTR)"\2330 p";
  195.                 wc_ConWrite -> io_Length    = -1;
  196.  
  197.                 DoIO(wc_ConWrite);
  198.  
  199.                 wc_ConWrite -> io_Data        = (APTR)wc_String;
  200.                 wc_ConWrite -> io_Length    = -1;
  201.  
  202.                 DoIO(wc_ConWrite);
  203.  
  204.                 wc_Success = TRUE;
  205.  
  206.                 CloseDevice(wc_ConWrite);
  207.             }
  208.  
  209.             DeleteStdIO(wc_ConWrite);
  210.         }
  211.  
  212.         DeletePort(wc_ConPort);
  213.     }
  214.  
  215.     return(wc_Success);
  216. }
  217.  
  218. BYTE
  219. PopRequest(struct Window *pr_ParentWindow,UBYTE *pr_TitleText,UBYTE *pr_BodyText,UBYTE *pr_PosText,UBYTE *pr_NegText,BYTE pr_Default)
  220. {
  221.     STATIC struct NewWindow pr_StaticNewWindow =
  222.     {
  223.         0,0,
  224.         0,1,
  225.         0,1,
  226.         VANILLAKEY | MOUSEBUTTONS | GADGETUP | CLOSEWINDOW | CLOSEWINDOW,
  227.         RMBTRAP | WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE,
  228.         (struct Gadget *)NULL,
  229.         (struct Image *)NULL,
  230.         (STRPTR)NULL,
  231.         (struct Screen *)NULL,
  232.         (struct BitMap *)NULL,
  233.         0,0,
  234.         0,0,
  235.         WBENCHSCREEN
  236.     };
  237.  
  238.     STATIC struct Gadget pr_StaticGadget =
  239.     {
  240.         (struct Gadget *)NULL,
  241.         0,0,
  242.         0,0,
  243.         GADGHBOX,
  244.         RELVERIFY | GADGIMMEDIATE,
  245.         BOOLGADGET,
  246.         (APTR)NULL,
  247.         (APTR)NULL,
  248.         (struct IntuiText *)NULL,
  249.         NULL,
  250.         (APTR)NULL,
  251.         0,
  252.         (APTR)NULL
  253.     };
  254.  
  255.     STATIC struct TextAttr pr_TextAttr =
  256.     {
  257.         (UBYTE *)"topaz.font",
  258.         8,
  259.         FS_NORMAL,
  260.         FPF_ROMFONT
  261.     };
  262.  
  263.     struct NewWindow    *pr_NewWindow;
  264.     struct Window        *pr_Window;
  265.     struct IntuiMessage    *pr_IMsg;
  266.     struct Gadget        *pr_PosGadget = NULL,*pr_NegGadget = NULL,*pr_TempGadget;
  267.  
  268.     struct Screen         pr_Screen,*pr_FrontScreen;
  269.     struct TextFont        *pr_TextFont;
  270.  
  271.     LONG             pr_Width,pr_Height;
  272.     BYTE             pr_Result = FALSE;
  273.     ULONG             pr_IntuiLock;
  274.  
  275.     if(!pr_BodyText)
  276.         return(pr_Result);
  277.  
  278.     if(!(pr_NewWindow = (struct NewWindow *)AllocMem(sizeof(struct NewWindow),MEMF_PUBLIC)))
  279.         return(pr_Result);
  280.  
  281.     CopyMem(&pr_StaticNewWindow,pr_NewWindow,sizeof(struct NewWindow));
  282.  
  283.     pr_IntuiLock = LockIBase(NULL);
  284.  
  285.     pr_FrontScreen = IntuitionBase -> FirstScreen;
  286.  
  287.     UnlockIBase(pr_IntuiLock);
  288.  
  289.     if(pr_ParentWindow)
  290.     {
  291.         pr_NewWindow -> Type    = CUSTOMSCREEN;
  292.         pr_NewWindow -> Screen    = pr_ParentWindow -> WScreen;
  293.     }
  294.     else
  295.         OpenWorkBench();
  296.  
  297.     if(!GetScreenData(&pr_Screen,sizeof(struct Screen),pr_NewWindow -> Type,pr_NewWindow -> Screen))
  298.     {
  299.         FreeMem(pr_NewWindow,sizeof(struct NewWindow));
  300.         return(pr_Result);
  301.     }
  302.  
  303.     CalcDimensions(pr_BodyText,&pr_Width,&pr_Height,(pr_Screen . Width - 6) / 8);
  304.  
  305.     if(pr_Height > (pr_Screen . Height - 15 - 13) / 8)
  306.     {
  307.         FreeMem(pr_NewWindow,sizeof(struct NewWindow));
  308.         return(pr_Result);
  309.     }
  310.  
  311.     pr_NewWindow -> Width    = pr_Width * 8 + 6 + 4;
  312.     pr_NewWindow -> Height    = pr_Height * 8 + GfxBase -> DefaultFont -> tf_YSize + 7 + 19 + 2;
  313.  
  314.     if(pr_TitleText)
  315.         pr_NewWindow -> Title = pr_TitleText;
  316.     else
  317.         pr_NewWindow -> Title = (UBYTE *)"System Request";
  318.  
  319.     if(!pr_PosText && !pr_NegText)
  320.         pr_NegText = (UBYTE *)"Continue?";
  321.  
  322.     if(pr_PosText)
  323.     {
  324.         if(!(pr_PosGadget = (struct Gadget *)AllocMem(sizeof(struct Gadget),MEMF_PUBLIC)))
  325.         {
  326.             FreeMem(pr_NewWindow,sizeof(struct NewWindow));
  327.             return(pr_Result);
  328.         }
  329.  
  330.         CopyMem(&pr_StaticGadget,pr_PosGadget,sizeof(struct Gadget));
  331.  
  332.         pr_PosGadget -> Width    = 8 * strlen((char *)pr_PosText) + 4;
  333.         pr_PosGadget -> Height    = 8 + 2;
  334.  
  335.         pr_PosGadget -> LeftEdge= 3 + 2 + 3;
  336.         pr_PosGadget -> TopEdge    = pr_NewWindow -> Height - 13 - 1;
  337.     }
  338.  
  339.     if(pr_NegText)
  340.     {
  341.         if(!(pr_NegGadget = (struct Gadget *)AllocMem(sizeof(struct Gadget),MEMF_PUBLIC)))
  342.         {
  343.             FreeMem(pr_NewWindow,sizeof(struct NewWindow));
  344.  
  345.             if(pr_PosGadget)
  346.                 FreeMem(pr_PosGadget,sizeof(struct Gadget));
  347.  
  348.             return(pr_Result);
  349.         }
  350.  
  351.         CopyMem(&pr_StaticGadget,pr_NegGadget,sizeof(struct Gadget));
  352.  
  353.         pr_NegGadget -> Width    = 8 * strlen((char *)pr_NegText) + 4;
  354.         pr_NegGadget -> Height    = 8 + 2;
  355.  
  356.         pr_Width = pr_NegGadget -> Width + 6 + 4 + 6;
  357.  
  358.         if(pr_PosGadget)
  359.             pr_Width += (pr_PosGadget -> Width + 12);
  360.  
  361.         if(pr_NewWindow -> Width < pr_Width)
  362.             pr_NewWindow -> Width = pr_Width;
  363.  
  364.         pr_NegGadget -> LeftEdge= pr_NewWindow -> Width - pr_NegGadget -> Width - 3 - 2 - 3;
  365.         pr_NegGadget -> TopEdge    = pr_NewWindow -> Height - 13 - 1;
  366.  
  367.         pr_NegGadget -> GadgetID= 1;
  368.     }
  369.  
  370.     if(!pr_NegGadget && pr_NewWindow -> Width < pr_PosGadget -> Width + 6 + 4 + 6)
  371.         pr_NewWindow -> Width = pr_PosGadget -> Width + 6 + 4 + 6;
  372.  
  373.     if(pr_Default && !pr_PosGadget)
  374.         pr_Default = FALSE;
  375.  
  376.     if(!pr_Default && !pr_NegGadget)
  377.         pr_Default = TRUE;
  378.  
  379.     if(pr_Default)
  380.         pr_TempGadget = pr_PosGadget;
  381.     else
  382.         pr_TempGadget = pr_NegGadget;
  383.  
  384.     pr_NewWindow -> LeftEdge= pr_Screen . MouseX - (pr_TempGadget -> LeftEdge + pr_TempGadget -> Width / 2);
  385.     pr_NewWindow -> TopEdge    = pr_Screen . MouseY - (pr_TempGadget -> TopEdge + pr_TempGadget -> Height / 2);
  386.  
  387.     while(pr_NewWindow -> LeftEdge < 0)
  388.         pr_NewWindow -> LeftEdge++;
  389.  
  390.     while(pr_NewWindow -> TopEdge < 0)
  391.         pr_NewWindow -> TopEdge++;
  392.  
  393.     while(pr_NewWindow -> LeftEdge + pr_NewWindow -> Width >= pr_Screen . Width)
  394.         pr_NewWindow -> LeftEdge--;
  395.  
  396.     while(pr_NewWindow -> TopEdge + pr_NewWindow -> Height >= pr_Screen . Height)
  397.         pr_NewWindow -> TopEdge--;
  398.  
  399.     if(!(pr_TextFont = (struct TextFont *)OpenFont(&pr_TextAttr)))
  400.     {
  401.         if(pr_PosGadget)
  402.             FreeMem(pr_PosGadget,sizeof(struct Gadget));
  403.  
  404.         if(pr_NegGadget)
  405.             FreeMem(pr_NegGadget,sizeof(struct Gadget));
  406.  
  407.         FreeMem(pr_NewWindow,sizeof(struct NewWindow));
  408.  
  409.         return(pr_Result);
  410.     }
  411.  
  412.     if(!(pr_Window = (struct Window *)OpenWindow(pr_NewWindow)))
  413.     {
  414.         CloseFont(pr_TextFont);
  415.  
  416.         if(pr_PosGadget)
  417.             FreeMem(pr_PosGadget,sizeof(struct Gadget));
  418.  
  419.         if(pr_NegGadget)
  420.             FreeMem(pr_NegGadget,sizeof(struct Gadget));
  421.  
  422.         FreeMem(pr_NewWindow,sizeof(struct NewWindow));
  423.  
  424.         return(pr_Result);
  425.     }
  426.  
  427.     SetFont(pr_Window -> RPort,pr_TextFont);
  428.  
  429.     SetAPen(pr_Window -> RPort,3);
  430.     SetBPen(pr_Window -> RPort,2);
  431.     SetDrMd(pr_Window -> RPort,JAM2);
  432.  
  433.     WriteConsole(pr_Window,pr_BodyText);
  434.  
  435.     if(pr_PosGadget)
  436.     {
  437.         AddGadget(pr_Window,pr_PosGadget,1);
  438.  
  439.         EraseGadget(pr_Window -> RPort,pr_PosGadget,2);
  440.  
  441.         Move(pr_Window -> RPort,pr_PosGadget -> LeftEdge + 2,pr_PosGadget -> TopEdge + 1 + pr_TextFont -> tf_Baseline);
  442.         Text(pr_Window -> RPort,(char *)pr_PosText,strlen((char *)pr_PosText));
  443.     }
  444.  
  445.     if(pr_NegGadget)
  446.     {
  447.         AddGadget(pr_Window,pr_NegGadget,1);
  448.  
  449.         EraseGadget(pr_Window -> RPort,pr_NegGadget,2);
  450.  
  451.         Move(pr_Window -> RPort,pr_NegGadget -> LeftEdge + 2,pr_NegGadget -> TopEdge + 1 + pr_TextFont -> tf_Baseline);
  452.         Text(pr_Window -> RPort,(char *)pr_NegText,strlen((char *)pr_NegText));
  453.     }
  454.  
  455.     MoveScreen(pr_Window -> WScreen,0,- pr_Window -> WScreen -> TopEdge);
  456.     ScreenToFront(pr_Window -> WScreen);
  457.     ActivateWindow(pr_Window);
  458.  
  459. Skip1:    FOREVER
  460.     {
  461.         ULONG pr_Class,pr_Code;
  462.         struct Gadget *pr_Gadget;
  463.  
  464.         WaitPort(pr_Window -> UserPort);
  465.  
  466.         if(pr_IMsg = (struct IntuiMessage *)GetMsg(pr_Window -> UserPort))
  467.         {
  468.             pr_Class    = pr_IMsg -> Class;
  469.             pr_Code        = pr_IMsg -> Code;
  470.             pr_Gadget    = (struct Gadget *)pr_IMsg -> IAddress;
  471.  
  472.             if(pr_Class == VANILLAKEY)
  473.                 pr_Code = toupper(pr_Code);
  474.  
  475.             ReplyMsg(pr_IMsg);
  476.  
  477.             if(pr_Class == GADGETUP)
  478.             {
  479.                 if(pr_Gadget -> GadgetID == 0)
  480.                     pr_Result = TRUE;
  481.  
  482.                 break;
  483.             }
  484.  
  485.             if(pr_Class == CLOSEWINDOW)
  486.                 break;
  487.  
  488.             if(pr_Class == VANILLAKEY)
  489.             {
  490.                 pr_Code = toupper(pr_Code);
  491.  
  492.                 if((pr_Code == 'Y' || pr_Code == 'J' || pr_Code == 'V' || pr_Code == 'C' || pr_Code == 'R' || pr_Code == '\r') && pr_PosText)
  493.                 {
  494.                     pr_Result = TRUE;
  495.                     break;
  496.                 }
  497.  
  498.                 if((pr_Code == 'N' || pr_Code == 'Q' || pr_Code == 'B' || pr_Code == '\33') && pr_NegText)
  499.                     break;
  500.  
  501.                 continue;
  502.             }
  503.         }
  504.     }
  505.  
  506.     CloseFont(pr_TextFont);
  507.  
  508.     if(pr_PosGadget)
  509.     {
  510.         RemoveGadget(pr_Window,pr_PosGadget);
  511.         FreeMem(pr_PosGadget,sizeof(struct Gadget));
  512.     }
  513.  
  514.     if(pr_NegGadget)
  515.     {
  516.         RemoveGadget(pr_Window,pr_NegGadget);
  517.         FreeMem(pr_NegGadget,sizeof(struct Gadget));
  518.     }
  519.  
  520.     FreeMem(pr_NewWindow,sizeof(struct NewWindow));
  521.  
  522.     pr_IntuiLock = LockIBase(NULL);
  523.  
  524.     if(pr_FrontScreen == IntuitionBase -> FirstScreen)
  525.         pr_FrontScreen = NULL;
  526.  
  527.     UnlockIBase(pr_IntuiLock);
  528.  
  529.     if(pr_FrontScreen)
  530.         ScreenToFront(pr_FrontScreen);
  531.  
  532.     CloseWindow(pr_Window);
  533.  
  534.     return(pr_Result);
  535. }
  536.  
  537.     /* UStrCmp():
  538.      *
  539.      *    strcmp function which ignores case.
  540.      */
  541.  
  542. BYTE
  543. UStrCmp(UBYTE *a,UBYTE *b)
  544. {
  545.     for( ; ToUpper(*a) == ToUpper(*b) ; a++, b++)
  546.     {
  547.         if(!(*a))
  548.             return(0);
  549.     }
  550.  
  551.     return(1);
  552. }
  553.  
  554.     /* GetToken(s,start):
  555.      *
  556.      *    Parse a string and split it into single tokens.
  557.      */
  558.  
  559. UBYTE *
  560. GetToken(UBYTE *s,LONG *start)
  561. {
  562.     static UBYTE    buffer[256];
  563.     LONG        i,end = 0,quote = FALSE,maxlen = strlen(s);
  564.     char        t;
  565.  
  566.     if(maxlen > 255)
  567.         maxlen = 255;
  568.  
  569.     if(*start > strlen(s) - 1 || !strlen(s) || !s)
  570.         return(NULL);
  571.  
  572.     for(i = *start ; i <= maxlen ; i++)
  573.     {
  574.         if(!end && (s[i] == ' ' || s[i] == '\t'))
  575.         {
  576.             while((s[i] == ' ' || s[i] == '\t') && i < maxlen)
  577.             {
  578.                 i++;
  579.                 (*start)++;
  580.             }
  581.         }
  582.  
  583.         t = s[i];
  584.  
  585.         if(!end && t == '+')
  586.         {
  587.             (*start)++;
  588.             continue;
  589.         }
  590.  
  591.         if(!end && t == '=')
  592.         {
  593.             strcpy(buffer,"=");
  594.             (*start)++;
  595.  
  596.             return(buffer);
  597.         }
  598.  
  599.         if(s[i] == '\\' && s[i + 1] == '\"')
  600.         {
  601.             i += 2;
  602.  
  603.             end = i - *start + 1;
  604.  
  605.             t = s[i];
  606.         }
  607.  
  608.         if(t == '\"' && !quote)
  609.         {
  610.             quote = TRUE;
  611.  
  612.             (*start)++;
  613.  
  614.             end++;
  615.  
  616.             continue;
  617.         }
  618.  
  619.         if((t == '+' || t == '=' || t == ' ' || t == '\t' || t == ';') && quote)
  620.         {
  621.             end++;
  622.             continue;
  623.         }
  624.  
  625.         if((t == '+' || t == '\n' || t == '=' || t == ' ' || t == 0) || (t == '\"' && quote) || (t == ';' && !quote))
  626.         {
  627.             if(t == ';' && !end)
  628.                 return(NULL);
  629.  
  630.             if(t == '\"')
  631.             {
  632.                 strncpy(buffer,s + *start,end - 1);
  633.                 buffer[end - 1] = 0;
  634.             }
  635.             else
  636.             {
  637.                 strncpy(buffer,s + *start,end);
  638.                 buffer[end] = 0;
  639.             }
  640.  
  641.             (*start) += end;
  642.  
  643.             return(buffer);
  644.         }
  645.  
  646.         end++;
  647.     }
  648.  
  649.     return(NULL);
  650. }
  651.  
  652.     /* AddMacroKey(MacroKey):
  653.      *
  654.      *    Add a macro key to the big list.
  655.      */
  656.  
  657. struct MacroKey *
  658. AddMacroKey(struct MacroKey *MacroKey)
  659. {
  660.     struct MacroKey    *TheKey = NULL;
  661.     LONG         i;
  662.  
  663.     for(i = 0 ; i < MAXMACROS ; i++)
  664.     {
  665.         if(KeyList[i] . mk_Type == MK_UNUSED)
  666.         {
  667.             TheKey = &KeyList[i];
  668.             break;
  669.         }
  670.     }
  671.  
  672.     if(!TheKey)
  673.         return(NULL);
  674.  
  675.     CopyMem(MacroKey,TheKey,sizeof(struct MacroKey));
  676.  
  677.     return(TheKey);
  678. }
  679.  
  680.     /* Interprete(String,Line):
  681.      *
  682.      *    Interprete a command line from the config file.
  683.      */
  684.  
  685. BYTE
  686. Interprete(UBYTE *String,LONG Line)
  687. {
  688.     ULONG             Qualifier = 0;
  689.     ULONG             Code = -1;
  690.     struct InputEvent     FakeEvent;
  691.     struct MacroKey         NewKey;
  692.  
  693.     LONG             Start = 0,Key = FALSE,i,KeyCount = 0;
  694.     volatile LONG         QuitLoop;
  695.     UBYTE            *Token,*CommandString,*WindowName = NULL,Recognized = FALSE;
  696.  
  697.     UBYTE             KeyBuff1[40],KeyBuff2[40];
  698.  
  699.     if(String[strlen(String) - 1] == '\n')
  700.         String[strlen(String) - 1] = 0;
  701.  
  702.     if(Token = GetToken(String,&Start))
  703.     {
  704.         if(!UStrCmp("KEY",Token))
  705.             Key = TRUE;
  706.  
  707.         if(UStrCmp("COMMAND",Token) && !Key)
  708.         {
  709.             SimpleRequest("Line %ld: Unknown keyword:\n\n'%s'",Line,String);
  710.             return(FALSE);
  711.         }
  712.     }
  713.     else
  714.         return(TRUE);
  715.  
  716.     FOREVER
  717.     {
  718.         if(Token = GetToken(String,&Start))
  719.         {
  720.             QuitLoop = TRUE;
  721.  
  722.             for(i = 0 ; i < 9 ; i++)
  723.             {
  724.                 if(!UStrCmp(QualifierTab[i] . ka_Name,Token))
  725.                 {
  726.                     Recognized = TRUE;
  727.                     QuitLoop = FALSE;
  728.  
  729.                     Qualifier |= QualifierTab[i] . ka_Key;
  730.                 }
  731.             }
  732.         }
  733.         else
  734.             break;
  735.  
  736.         if(QuitLoop)
  737.             break;
  738.     }
  739.  
  740.     if(!Recognized)
  741.     {
  742.         SimpleRequest("Line %ld: Didn't recognize qualifier:\n\n'%s'",Line,String);
  743.         return(FALSE);
  744.     }
  745.  
  746.     if(Token)
  747.         goto JumpIn;
  748.  
  749.     if(Token = GetToken(String,&Start))
  750.     {
  751. JumpIn:        for(i = 0 ; i < 22 ; i++)
  752.         {
  753.             if(!UStrCmp(KeyTab[i] . ka_Name,Token))
  754.             {
  755.                 Code = KeyTab[i] . ka_Key;
  756.                 goto Next;
  757.             }
  758.         }
  759.  
  760.         if(KeyInvert(Token[0],&FakeEvent,MSeg -> DefaultKeyMap))
  761.             Code = FakeEvent . ie_Code;
  762.     }
  763.  
  764.     if(Code == -1)
  765.     {
  766.         SimpleRequest("Line %ld: Didn't recognize key:\n\n'%s'",Line,String);
  767.         return(FALSE);
  768.     }
  769.  
  770. Next:    FOREVER
  771.     {
  772.         if(Token = GetToken(String,&Start))
  773.         {
  774.             if(!UStrCmp("=",Token))
  775.                 break;
  776.         }
  777.         else
  778.         {
  779.             SimpleRequest("Line %ld: Statement '=' missing:\n\n'%s'",Line,String);
  780.             return(FALSE);
  781.         }
  782.     }
  783.  
  784.     if(Token = GetToken(String,&Start))
  785.         strcpy(KeyBuff1,Token);
  786.     else
  787.     {
  788.         SimpleRequest("Line %ld: Didn't find macro:\n\n'%s'",Line,String);
  789.         return(FALSE);
  790.     }
  791.  
  792.     if(Key)
  793.         goto AddIt;
  794.  
  795.     if(!(Token = GetToken(String,&Start)))
  796.         goto AddIt;
  797.  
  798.     if(UStrCmp("WINDOW",Token))
  799.     {
  800.         SimpleRequest("Line %ld: Didn't recognize 'WINDOW' statement:\n\n'%s'",Line,String);
  801.         return(FALSE);
  802.     }
  803.  
  804.     if(!(Token = GetToken(String,&Start)))
  805.     {
  806.         SimpleRequest("Line %ld: Didn't find window title:\n\n'%s'",Line,String);
  807.         return(FALSE);
  808.     }
  809.  
  810.     if(!(WindowName = (UBYTE *)AllocRem(strlen(Token) + 1,MEMF_PUBLIC)))
  811.     {
  812.         SimpleRequest("Can't allocate memory chunk!");
  813.         return(FALSE);
  814.     }
  815.  
  816.     strcpy(WindowName,Token);
  817.  
  818. AddIt:    for(i = 0 ; i < strlen(KeyBuff1) ; i++)
  819.     {
  820.         UBYTE c;
  821.  
  822.         if(KeyBuff1[i] != '\\')
  823.         {
  824.             KeyBuff2[KeyCount++] = KeyBuff1[i];
  825.             continue;
  826.         }
  827.  
  828.         if(i == strlen(KeyBuff1) - 1)
  829.             break;
  830.  
  831.         i++;
  832.  
  833.         c = 0;
  834.  
  835.         switch(ToUpper(KeyBuff1[i]))
  836.         {
  837.             case 'U':    c = KC_CURSORUP;
  838.                     break;
  839.  
  840.             case 'D':    c = KC_CURSORDOWN;
  841.                     break;
  842.  
  843.             case 'L':    c = KC_CURSORLEFT;
  844.                     break;
  845.  
  846.             case 'R':    c = KC_CURSORRIGHT;
  847.                     break;
  848.  
  849.             case 'H':    c = KC_HELP;
  850.                     break;
  851.  
  852.             case 'B':    c = 8;
  853.                     break;
  854.  
  855.             case 'E':    c = 127;
  856.                     break;
  857.  
  858.             case 'F':    if(i == strlen(KeyBuff1) - 1)
  859.                         break;
  860.  
  861.                     i++;
  862.  
  863.                     if(!isdigit(KeyBuff1[i]))
  864.                         break;
  865.  
  866.                     if(!KeyBuff1[i] == '1')
  867.                     {
  868.                         c = KC_FKEY1 + KeyBuff1[i] - '1';
  869.                         break;
  870.                     }
  871.  
  872.                     if(i == strlen(KeyBuff1) - 1)
  873.                         break;
  874.  
  875.                     i++;
  876.  
  877.                     if(!isdigit(KeyBuff1[i]))
  878.                     {
  879.                         c = KC_FKEY1;
  880.                         break;
  881.                     }
  882.  
  883.                     if(KeyBuff1[i] != '0')
  884.                         break;
  885.  
  886.                     c = KC_FKEY10;
  887.                     break;
  888.  
  889.             case 'N':    c = '\n';
  890.                     break;
  891.  
  892.             case '\\':    c = '\\';
  893.                     break;
  894.  
  895.             default:    c = KeyBuff1[i];
  896.  
  897.                     break;
  898.         }
  899.  
  900.         if(c)
  901.             KeyBuff2[KeyCount++] = c;
  902.     }
  903.  
  904.     KeyBuff2[KeyCount] = 0;
  905.  
  906.     if(!(CommandString = (UBYTE *)AllocRem(strlen(KeyBuff2) + 1,MEMF_PUBLIC)))
  907.     {
  908.         SimpleRequest("Can't allocate memory chunk!");
  909.         FreeRem(WindowName);
  910.  
  911.         return(FALSE);
  912.     }
  913.  
  914.     strcpy(CommandString,KeyBuff2);
  915.  
  916.     memset(&NewKey,0,sizeof(struct MacroKey));
  917.  
  918.     NewKey . mk_CommandKey        = Code;
  919.     NewKey . mk_CommandQualifier    = Qualifier;
  920.  
  921.     NewKey . mk_String        = CommandString;
  922.     NewKey . mk_Window        = WindowName;
  923.  
  924.     if(Key)
  925.         NewKey . mk_Type    = MK_WORD;
  926.     else
  927.         NewKey . mk_Type    = MK_COMMAND;
  928.  
  929.     if(AddMacroKey(&NewKey))
  930.         return(TRUE);
  931.  
  932.     SimpleRequest("Line %ld: Key macro table full.",Line);
  933.     return(FALSE);
  934. }
  935.  
  936.     /* UpdateList(Name):
  937.      *
  938.      *    Update the big macro key list.
  939.      */
  940.  
  941. BYTE
  942. UpdateList(char *Name)
  943. {
  944.     char         LineBuff[257];
  945.     LONG         LineNum = 1;
  946.     ARPFileHandle    *ConfigFile;
  947.  
  948.     if(!Name)
  949.         Name = "S:KeyMacro.config";
  950.  
  951.     if(!(KeyList = (struct MacroKey *)AllocRem(sizeof(struct MacroKey) * MAXMACROS,MEMF_PUBLIC | MEMF_CLEAR)))
  952.     {
  953.         SimpleRequest("Can't allocate memory chunk!");
  954.         return(FALSE);
  955.     }
  956.  
  957.     GetDefaultKeyMap();
  958.  
  959.     if(ConfigFile = OpenARPFile(Name,MODE_OLDFILE,976))
  960.     {
  961.         while(FGetsARP(LineBuff,256,ConfigFile))
  962.         {
  963.             if(!Interprete(LineBuff,LineNum++))
  964.             {
  965.                 CloseARPFile(ConfigFile);
  966.  
  967.                 FreeRem(KeyList);
  968.  
  969.                 return(FALSE);
  970.             }
  971.         }
  972.  
  973.         CloseARPFile(ConfigFile);
  974.     }
  975.     else
  976.     {
  977.         SimpleRequest("Couldn't open configuration file!");
  978.         FreeRem(KeyList);
  979.  
  980.         return(FALSE);
  981.     }
  982.  
  983.     return(TRUE);
  984. }
  985.  
  986. BYTE
  987. GetDefaultKeyMap()
  988. {
  989.     struct IOStdReq    *ConsoleRequest;
  990.     struct MsgPort    *ConsolePort;
  991.     BYTE         Result = FALSE;
  992.  
  993.     if(ConsolePort = CreatePort(NULL,0))
  994.     {
  995.         if(ConsoleRequest = CreateStdIO(ConsolePort))
  996.         {
  997.             if(!OpenDevice("console.device",CONU_STANDARD,ConsoleRequest,0))
  998.             {
  999.                 ConsoleRequest -> io_Command    = CD_ASKDEFAULTKEYMAP;
  1000.                 ConsoleRequest -> io_Length    = sizeof(struct KeyMap);
  1001.                 ConsoleRequest -> io_Data    = (APTR)MSeg -> DefaultKeyMap;
  1002.                 ConsoleRequest -> io_Flags    = IOF_QUICK;
  1003.  
  1004.                 if(!DoIO(ConsoleRequest))
  1005.                     Result = TRUE;
  1006.  
  1007.                 CloseDevice(ConsoleRequest);
  1008.             }
  1009.  
  1010.             DeleteStdIO(ConsoleRequest);
  1011.         }
  1012.  
  1013.         DeletePort(ConsolePort);
  1014.     }
  1015.  
  1016.     return(Result);
  1017. }
  1018.  
  1019.     /* main(argc,argv):
  1020.      *
  1021.      *    The entry point to this program.
  1022.      */
  1023.  
  1024. VOID
  1025. main(int argc,char **argv)
  1026. {
  1027.     struct Process    *ThatsMe = (struct Process *)SysBase -> ThisTask;
  1028.     char        *FileName = argv[ARG_STARTUP];
  1029.     LONG         Created = FALSE;
  1030.     LONG         i;
  1031.  
  1032.         /* No ^C trapping, please. */
  1033.  
  1034.     Enable_Abort = FALSE;
  1035.  
  1036.         /* Started from Workbench? */
  1037.  
  1038.     if(!From_CLI)
  1039.         FileName = NULL;
  1040.  
  1041.         /* Look if handler process is already running. */
  1042.  
  1043.     MSeg = (struct MSeg *)FindPort(PORTNAME);
  1044.  
  1045.         /* Short info? */
  1046.  
  1047.     if(argv[ARG_INFO])
  1048.     {
  1049.         Printf("\n\33[1m\33[33mKeyMacro\33[31m\33[0m the Amiga macro key handler.\n\n");
  1050.  
  1051.         Printf("         This program may be non-commercially\n");
  1052.         Printf("         redistributed!\n\n");
  1053.  
  1054.         Printf("\33[1m\33[33mAuthor\33[31m\33[0m - Olaf Barthel, MXM\n");
  1055.         Printf("         Brabeckstrasse 35\n");
  1056.         Printf("         D-3000 Hannover 71\n\n");
  1057.  
  1058.         Printf("     Federal Republic of Germany.\n\n");
  1059.  
  1060.         exit(RETURN_OK);
  1061.     }
  1062.  
  1063.         /* Remove the handler? */
  1064.  
  1065.     if(argv[ARG_QUIT])
  1066.     {
  1067.         Printf("Removing \33[1m\33[33mKeyMacro\33[31m\33[0m, ");
  1068.  
  1069.         if(!MSeg)
  1070.         {
  1071.             Printf("failed!\a\n");
  1072.  
  1073.             exit(RETURN_OK);
  1074.         }
  1075.  
  1076.         MSeg -> Father = (struct Task *)SysBase -> ThisTask;
  1077.  
  1078.         if(MSeg -> Child)
  1079.         {
  1080.             Signal(MSeg -> Child,SIG_CLOSE);
  1081.             Wait(SIG_CLOSE);
  1082.         }
  1083.  
  1084.         RemPort(&MSeg -> Port);
  1085.  
  1086.         FreeMem(MSeg -> Port . mp_Node . ln_Name,sizeof(PORTNAME));
  1087.  
  1088.         if(MSeg -> Segment)
  1089.             UnLoadSeg(MSeg -> Segment);
  1090.  
  1091.         if(MSeg -> MacroList)
  1092.         {
  1093.             for(i = 0 ; i < MSeg -> NumMacros ; i++)
  1094.             {
  1095.                 if(MSeg -> MacroList[i] . mk_Type == MK_UNUSED)
  1096.                     continue;
  1097.  
  1098.                 if(MSeg -> MacroList[i] . mk_String)
  1099.                     FreeRem(MSeg -> MacroList[i] . mk_String);
  1100.  
  1101.                 if(MSeg -> MacroList[i] . mk_Window)
  1102.                     FreeRem(MSeg -> MacroList[i] . mk_Window);
  1103.             }
  1104.  
  1105.             FreeRem(MSeg -> MacroList);
  1106.         }
  1107.  
  1108.         FreeRem(MSeg -> DefaultKeyMap);
  1109.         FreeRem(MSeg);
  1110.  
  1111.         Printf("OK.\n");
  1112.  
  1113.         exit(RETURN_OK);
  1114.     }
  1115.  
  1116.         /* Allocate the handler data. */
  1117.  
  1118.     if(!MSeg)
  1119.     {
  1120.         if(MSeg = (struct MSeg *)AllocRem(sizeof(struct MSeg),MEMF_PUBLIC | MEMF_CLEAR))
  1121.         {
  1122.             MSeg -> Port . mp_Flags            = PA_IGNORE;
  1123.             MSeg -> Port . mp_Node . ln_Pri        = 0;
  1124.             MSeg -> Port . mp_Node . ln_Type    = NT_MSGPORT;
  1125.             MSeg -> Port . mp_Node . ln_Name    = AllocMem(sizeof(PORTNAME),MEMF_PUBLIC);
  1126.             MSeg -> Child                = NULL;
  1127.             MSeg -> Father                = (struct Task *)SysBase -> ThisTask;
  1128.             MSeg -> SegSize                = sizeof(struct MSeg);
  1129.             MSeg -> RingBack            = SIGBREAKF_CTRL_C;
  1130.             MSeg -> Revision            = REVISION;
  1131.  
  1132.             NewList(&MSeg -> Port . mp_MsgList);
  1133.  
  1134.             if(From_CLI)
  1135.             {
  1136.                 Printf("\33[1m\33[33mKeyMacro v1.%ld \33[31m\33[0m© Copyright 1989, 1990 by \33[4mMXM\33[0m, All rights reserved.\n",REVISION);
  1137.  
  1138.                 Printf("Installing \33[33m\33[1mKeyMacro\33[0m\33[31m, ");
  1139.             }
  1140.  
  1141.             if(MSeg -> Port . mp_Node . ln_Name)
  1142.                 strcpy(MSeg -> Port . mp_Node . ln_Name,PORTNAME);
  1143.             else
  1144.             {
  1145. Failed:                FreeRem(MSeg);
  1146.  
  1147.                 if(From_CLI)
  1148.                     Printf("failed!\a\n");
  1149.  
  1150.                 exit(RETURN_FAIL);
  1151.             }
  1152.  
  1153.             if(!(MSeg -> DefaultKeyMap = (struct KeyMap *)AllocPub(sizeof(struct KeyMap))))
  1154.                 goto Failed;
  1155.  
  1156.             if(!(MSeg -> Segment = LoadSeg("KeyMacro-Handler")))
  1157.                 MSeg -> Segment = LoadSeg("L:KeyMacro-Handler");
  1158.  
  1159.             if(!MSeg -> Segment)
  1160.             {
  1161.                 if(From_CLI)
  1162.                     Printf("unable to find \33[33mL:KeyMacro-Handler\33[31m\a!\n");
  1163.  
  1164.                 FreeRem(MSeg -> DefaultKeyMap);
  1165.                 FreeRem(MSeg -> Port . mp_Node . ln_Name);
  1166.                 FreeRem(MSeg);
  1167.  
  1168.                 exit(RETURN_FAIL);
  1169.             }
  1170.             else
  1171.             {
  1172.                 AddPort(&MSeg -> Port);
  1173.  
  1174.                 if(!CreateProc("KeyMacro-Handler",10,MSeg -> Segment,4096))
  1175.                     goto NoMem;
  1176.  
  1177.                 Wait(SIGBREAKF_CTRL_C);
  1178.  
  1179.                 if(!MSeg -> Child)
  1180.                 {
  1181. NoMem:                    if(From_CLI)
  1182.                         Printf("\33[33mFAILED!\33[31m (care to retry?)\n");
  1183.  
  1184.                     RemPort(&MSeg -> Port);
  1185.  
  1186.                     FreeRem(MSeg -> DefaultKeyMap);
  1187.                     FreeRem(MSeg -> Port . mp_Node . ln_Name);
  1188.  
  1189.                     if(MSeg -> Segment)
  1190.                         UnLoadSeg(MSeg -> Segment);
  1191.  
  1192.                     FreeRem(MSeg);
  1193.  
  1194.                     exit(RETURN_FAIL);
  1195.                 }
  1196.                 else
  1197.                 {
  1198.                     if(From_CLI)
  1199.                         Printf("initializing, ");
  1200.  
  1201.                     GetDefaultKeyMap();
  1202.  
  1203.                     if(From_CLI)
  1204.                         Puts("Okay.");
  1205.                     else
  1206.                         SimpleRequest("\33[1mKeyMacro\33[0m installed.");
  1207.  
  1208.                     Created = TRUE;
  1209.                 }
  1210.             }
  1211.         }
  1212.     }
  1213.  
  1214.     if(argv[ARG_DELAY])
  1215.     {
  1216.         LONG Value = Atol(argv[ARG_DELAY]);
  1217.  
  1218.         if(Value)
  1219.         {
  1220.             if(Value < 10000)
  1221.             {
  1222.                 if(From_CLI)
  1223.                     Printf("\33[1mKeyMacro:\33[0m Delay value too small - must be >= 10000!\n");
  1224.  
  1225.                 exit(RETURN_ERROR);
  1226.             }
  1227.         }
  1228.  
  1229.         MSeg -> Delay = Value;
  1230.     }
  1231.  
  1232.         /* Update the macro key list. */
  1233.  
  1234.     if(UpdateList(FileName))
  1235.     {
  1236.         if(Created)
  1237.         {
  1238.             MSeg -> NumMacros = MAXMACROS;
  1239.             MSeg -> MacroList = KeyList;
  1240.         }
  1241.         else
  1242.         {
  1243.             struct MacroMessage UpdateMsg;
  1244.  
  1245.             UpdateMsg . mm_Type        = MM_UPDATE;
  1246.             UpdateMsg . mm_NumMacros    = MAXMACROS;
  1247.             UpdateMsg . mm_MacroList    = KeyList;
  1248.  
  1249.             SendMacroMsg(&UpdateMsg,&MSeg -> Port);
  1250.  
  1251.             if(From_CLI)
  1252.                 Printf("\33[1mKeyMacro:\33[0m Updating macro keys...\n");
  1253.         }
  1254.     }
  1255.     else
  1256.         exit(RETURN_ERROR);
  1257.  
  1258.     exit(RETURN_OK);
  1259. }
  1260.